using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Forest.Cat.Domain.Entities;
using Forest.Core.Data;
using Forest.Core;
using Forest.Core.Caching;
using Forest.Core.Events;

namespace Forest.Cat.Domain.Services.Rankings
{
    public partial class RankingService : IRankingService
    {
        #region Constants
        private const string RANKING_BY_ID_KEY = "ranking.id-{0}";
        private const string RANKING_PATTERN_KEY = "ranking.";
        #endregion

        #region Fields
        private readonly IRepository<Ranking> _rankingRepository;
        private readonly ICacheManager _cacheManager;
        private readonly IEventPublisher _eventPublisher;
        #endregion

        #region Ctor
        public RankingService(IRepository<Ranking> rankingRepository, ICacheManager cacheManager, IEventPublisher eventPublisher)
        {
            _rankingRepository = rankingRepository;
            _cacheManager = cacheManager;
            _eventPublisher = eventPublisher;
        }
        #endregion

        #region Base Methods
        public virtual void DeleteRanking(Ranking ranking)
        {
            if (ranking == null)
                throw new ArgumentNullException("Ranking");

            _rankingRepository.Delete(ranking);
            _cacheManager.RemoveByPattern(RANKING_PATTERN_KEY);
            _eventPublisher.EntityDeleted(ranking);
        }

        public Ranking GetRankingById(Guid rankingId)
        {
            if (rankingId == Guid.Empty)
                return null;
            string key = string.Format(RANKING_BY_ID_KEY, rankingId);

            return _cacheManager.Get(key, () =>
            {
                var cl = _rankingRepository.GetById(rankingId);
                return cl;
            });
        }

        public virtual IPagedList<Ranking> GetAllRankings(int pageIndex, int pageSize)
        {
            var query = _rankingRepository.Table;
            query = query.OrderBy(w => w.Id);
            var items = new PagedList<Ranking>(query, pageIndex, pageSize);
            return items;
        }

        public virtual void InsertRanking(Ranking ranking)
        {
            if (ranking == null)
                throw new ArgumentNullException("Ranking");
            _rankingRepository.Insert(ranking);
            _cacheManager.RemoveByPattern(RANKING_PATTERN_KEY);
            _eventPublisher.EntityInserted(ranking);
        }

        public virtual void UpdateRanking(Ranking ranking)
        {
            if (ranking == null)
                throw new ArgumentNullException("Ranking");
            _rankingRepository.Update(ranking);
            _cacheManager.RemoveByPattern(RANKING_PATTERN_KEY);
            _eventPublisher.EntityUpdated(ranking);
        }
        #endregion

        #region Extend Methods

        public IList<Ranking> GetRankingForHome(int areaCode, int count) 
        {
            return _rankingRepository.Table.Where(item => item.AreaCode.Value.Equals(areaCode)).OrderByDescending(x=>x.OrderNumber).Take(count).ToList();
        }

        #endregion
    }
}
